﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.IO.Ports;
using Modbus.Device;
using ModbusTestTool.Error_Logging;
using System.Net.Sockets;

namespace ModbusTestTool.Singeltons
{
    public class Settings
    {
        public struct state
        {
            public string tag;
            public string fileName;
            public string comPort;
            public byte modbusId;
            public int baudSpeed;
            public string testFileName;
            public string address;
            public int port;
            public serialOrTcp serialOrTcpSelect { set; get; }
        }


        TcpClient tcpPort;
        public enum serialOrTcp { serial, tcp };
        



        public static object lockVar = new object();
        public state State = new state() { tag="Default",fileName = "default", comPort = "com1", baudSpeed = 9600, modbusId = 49, testFileName = "none.txt",address = "127.0.0.1",port=81 };
        static private Settings _Instance = new Settings();
        private SerialPort port;
        public ModbusMaster master;

     

        public static Settings Instance
        {
            get
            {
                return _Instance;
            }
        }



        private Settings()
        {
            State.serialOrTcpSelect = serialOrTcp.serial;
            try
            {
                ReadCurrentState();
            }
            catch (Exception err)
            {
                ErrorLog.Instance.addMessage(err.Message);
                State = new state() { fileName = "default", comPort = "com1", baudSpeed = 9600, modbusId = 49, testFileName = "none.txt", address = "127.0.0.1", port = 81 };
            }
        }

        public void  ReadCurrentState()
        {
            using (Stream inHandle = File.Open("state.xml", FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
            {
                XmlSerializer xIn = new XmlSerializer(typeof(state));
                State = (state)xIn.Deserialize(inHandle);
                
            }

            SetupModbusPorts();

            
        }

        public void SaveCurrentState()
        {
            using (StreamWriter outHandle = new StreamWriter("state.xml"))
            {
                XmlSerializer xOut = new XmlSerializer(typeof(state));
                xOut.Serialize(outHandle, State);
            }

        }

        ~Settings()
        {
            SaveCurrentState();
        }

        // depedning on if serial or tcp is selected the appropriate thing is selected
        public void SetupModbusPorts()
        {
            //int retry = 0;
        //setupState:
            try
            {
                if (State.serialOrTcpSelect == serialOrTcp.serial)
                {

                    if (port != null)
                    {
                        ((IDisposable) port).Dispose();
                    }
                    
                    port = new SerialPort(State.comPort, State.baudSpeed, Parity.None, 8, StopBits.One);
                    master = ModbusSerialMaster.CreateRtu(port);
                }
                else
                {
                    //tcpPort = new TcpClient(State.address, State.port);
                    //master = ModbusIpMaster.CreateIp(tcpPort);
                    //master = ModbusSerialMaster.CreateRtu(tcpPort);
                }
            }
            catch (Exception err)
            {
                ErrorLog.Instance.addMessage(err.Message);
                //ReadCurrentState();
                //if (retry < 5)
                //{
                //    retry++;
                //    goto setupState;
                //}
            }
        }

        public void openPort()
        {
            if (State.serialOrTcpSelect == serialOrTcp.serial)
            {
                if (!port.IsOpen)
                {
                    port.Open();
                }
            }
            if (State.serialOrTcpSelect == serialOrTcp.tcp)
            {
                if(!tcpPort.Connected)
                    tcpPort.Connect(State.address, State.port);
            }
        }

        public void closePort()
        {
            if (State.serialOrTcpSelect == serialOrTcp.serial)
            {
                if (port.IsOpen)
                {
                    port.Close();
                }
            }
            else
            {
                if (tcpPort.Connected) 
                    tcpPort.Close();
            }
        }

        public void updatePort()
        {
            closePort();
            port.BaudRate = State.baudSpeed;
            port.PortName = State.comPort;
            openPort();
        }

        public bool isPortOpen()
        {
            return port.IsOpen;
        }
    
    }
}
